/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "ui曲线编辑器.h"
#include "A_引擎/文件工程/工程文件.h"


static bool g移动视口 = false;
static bool g纵向缩放 = false;
static bool g移动控制点 = false;

static uint32	g网格线绘制属性 = 0;
static uint32	g曲线绘制属性 = 0;
static vec2		g节点鼠标局部位置 = { 0,0 };


static vec2 g选框起点坐标;
static vec2 g选框终点坐标;

C_曲线编辑视口*				C_曲线编辑视口::g当前操作曲线视口 = nullptr;
std::set<C_曲线编辑视口*>	C_曲线编辑视口::g_曲线视口页面;






bool f_曲线编辑视口_刷新绘制() {

	for (auto& e : C_曲线编辑视口::g_曲线视口页面) {
		if (!e->m_被裁剪) {
			//f_时间工作区_刷新时间线绘制(e, e->m_时间线绘制, f_NodeCtx_get帧().当前帧, e->m_父部件->m_Size.y);

			e->mui_状态条->m_当前帧.m_UI->m_Set(e->mui_状态条->m_当前帧);
			e->mui_状态条->m_帧区间.m_UI->m_Set(e->mui_状态条->m_帧区间);
		}
	}

	return true;
}

static void f_当前帧PropUpdate(S_Props& prop) {
	f_曲线编辑视口_刷新绘制();
	f_工作区_联动更新(E_工作区类型::e_曲线视口, E_工作区操作类型::e_所有);
}

static void on_播放控制(S_Props& prop) {

	switch (f_prop_enum(prop)) {
		case 0: {
			S_框架::g_播放帧 = false;
			f_时间工作区_帧步进(-1);
			f_曲线编辑视口_刷新绘制();
			//f_时间工作区_更新状态栏(true);
			break;
		}
		case 1: {
			
			S_框架::g_播放帧 = false;
			//f_时间工作区_更新状态栏(S_框架::g_播放帧);
			f_node_帧更新(S_框架::g_播放帧);
			break;
		}
		case 2: {
			S_框架::g_播放帧 = true;
			
			f_node_帧更新(S_框架::g_播放帧);
			break;
		}
		case 3: {
			S_框架::g_播放帧 = false;
			f_时间工作区_帧步进(1);
			f_曲线编辑视口_刷新绘制();
			
			break;
		}
		default:
			break;
	}
	
	f_工作区_联动更新(E_工作区类型::e_曲线视口, E_工作区操作类型::e_所有);
}



static void on_切换曲线过滤类型(S_Props& prop) {
	uint32 fb = f_prop_UI32位域枚举(prop);


}



C_曲线编辑视口状态条::C_曲线编辑视口状态条(S_UI渲染环境& ctx) : C_状态条(ctx) {
	m_过滤类型 = f_alloc_FlagBitsEnumProp(nullptr, *S_框架::g_曲线视口数据类型, u"过滤类型", 7);
	m_过滤类型.m_UI->m_Update = on_切换曲线过滤类型;
	m_过滤类型.m_私有 = true;


	m_播放按钮 = f_alloc_EnumProp(nullptr,
		{ {u"倒放一帧", u"左一帧"}, {u"暂停", u"暂停"}, {u"播放", u"播放"}, {u"前放一帧", u"右一帧"} },
		u"播放控制",
		0);
	f_prop_enum(m_播放按钮) = 1;

	m_当前帧 = f_alloc_I32Prop(&f_NodeCtx_get帧().当前帧, u"当前帧");
	m_帧区间 = f_alloc_iVec2Prop(&f_NodeCtx_get帧().帧区间, u"帧区间");
	


	m_播放按钮.m_私有 = true;
	m_当前帧.m_私有 = true;
	m_当前帧.m_私有 = true;

}

void C_曲线编辑视口状态条::f_重构() {
	std::vector<S_Props> props;
	S_Props	prop;

	prop = f_alloc_NoneProp();
	props.push_back(prop);

	props.push_back(m_播放按钮);

	prop = f_alloc_NoneProp();
	props.push_back(prop);

	props.push_back(m_当前帧);
	props.push_back(m_帧区间);


	m_播放按钮.m_UI->m_Update = f_当前帧PropUpdate;
	m_当前帧.m_UI->m_Update = f_当前帧PropUpdate;
	m_帧区间.m_UI->m_Update = f_当前帧PropUpdate;

	f_构建属性部件(props, nullptr);
}





static void on_曲线视口布局(C_Widget* self, C_Widget** w, uint32 num) {
	//f_Widget_保持偏移比例(self);
}

void on_曲线视口绘制(C_Widget* self, S_2D画布* 画布) {
	C_曲线编辑视口& box = *(C_曲线编辑视口*)self;

	
}

void on_曲线视口变换修改(C_Widget* self) {
	C_曲线编辑视口& box = *(C_曲线编辑视口*)self;


	//S_2D_PanelAttr 属性 = { {1,1}, {0,0}, 1, 3 };
	//属性.m_渐变数量 = box->m_GPU内存分配维度大小.x;
	//f_vg_set属性(self->m_画布, box->m_背景绘制.m_属性, 属性);
	
	//属性 = { {1,1}, {0,0}, 1, 3 };
	//属性.m_Scale = self->m_扩展视口属性->m_比例;
	//属性.m_Offset = self->m_扩展视口属性->m_中心;
	//属性.m_渐变数量 = box->m_GPU内存分配维度大小.x;
	//属性.m_间隔 = 3;
	//f_vg_set属性(self->m_画布, g网格线绘制属性, 属性);

	//属性 = { {1,1}, {0,0}, 1, 3 };
	//属性.m_Offset = {self->m_扩展视口属性->m_中心.x, 0};
	//f_vg_set属性(self->m_画布, box->m_标签绘制.m_画布属性, 属性);

	//mat3X2 mat;
	//mat.row0 = {};
	//mat.row1 = self->m_Size;
	//mat.row2 = {1,0};

	//box->m_背景绘制.f_alloc(3);
	//box->m_背景绘制.f_set单色填充(0, mat, S_主题颜色::uic_工作区页面背景, S_Widget预设凸包图元::m_矩形);
	//mat = f_时间工作区_时间区间绘制矩阵(self);
	//mat.row1.y = self->m_Size.y;
	//box->m_背景绘制.f_set单色填充(1, mat, S_主题颜色::uic_时间轴时间区, S_Widget预设凸包图元::m_矩形);

	//box->m_选框线绘制.f_alloc(1);
	//box->m_选框线绘制.f_set单色填充(0, mat, {50, 50, 200, 255}, S_Widget预设图元::m_矩形);

	//vec2 帧绘制间隔宽度 = mat.row1;
	//vec2 刻度线步进宽度 = f_时间工作区_计算尺线绘制间隔(帧绘制间隔宽度);

	//box->m_刻度线绘制.f_alloc(1);
	//mat.row0 = {};
	//mat.row1 = self->m_Size;
	//mat.row2 = 刻度线步进宽度 * 2;
	//box->m_刻度线绘制.f_set(2048, mat, S_主题颜色::uic_时间网格线);
	
	//属性 = { {1,1}, {0,0}, 1, 3 };
	//属性.m_Scale = self->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放;
	//属性.m_Offset = self->m_扩展视口属性->m_中心;
	//属性.m_渐变数量 = box->m_GPU内存分配维度大小.x;
	//f_vg_set属性(self->m_画布, g曲线绘制属性, 属性);
	

	//box->m_是否未绘制 = false;
	//box->f_重建曲线绘制();
	
	//vec2 数量步进 = f_时间工作区_计算刻度文本_数量步进(帧绘制间隔宽度.x, 刻度线步进宽度.x);
	//f_时间工作区_时间线绘制(box, box->m_时间线绘制);
}

E_事件是否传递 on_曲线视口按键(C_Widget* self, const S_键盘& ks) {
	if (f_KS(ks, S_InputKey::e_KEY_左CTRL) == DEF_按键状态_按下中) {
		g纵向缩放 = true;
	}
	else {
		g纵向缩放 = false;
	}
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_曲线视口鼠标按下(C_Widget* self, const E_鼠标按钮& 按钮) {
	if (按钮 == E_鼠标按钮::e_鼠标中键) {
		g移动视口 = true;
	}
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_曲线视口鼠标放开(C_Widget* self, const E_鼠标按钮& 按钮) {
	if (按钮 == E_鼠标按钮::e_鼠标中键) {
		g移动视口 = false;
	}
	return E_事件是否传递::e_事件传递_终止;
}

bool on_曲线视口缩放(C_Widget* self, const S_鼠标& 鼠标) {
	vec2 s = {1,1};
	if (鼠标.lZ > 0) {
		if (g纵向缩放) {
			s.y = 1.15;
		}
		else {
			s.x = 1.15;
			s.y = 1.15;
		}
	}
	else if (鼠标.lZ < 0) {
		if (g纵向缩放) {
			s.y = 0.9;
		}
		else {
			s.x = 0.9;
			s.y = 0.9;
		}
	}
	f_C_Widget_鼠标位置视口缩放(self, s);
	return false;
}

static E_事件是否传递 on_曲线视口移动(C_Widget* self, const ivec4& value) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;
	C_曲线编辑视口::g当前操作曲线视口 = box;

	if (g移动视口) {
		self->m_扩展视口属性->m_中心.x += C_Widget::g_鼠标.abs.x;
		self->m_扩展视口属性->m_中心.y += C_Widget::g_鼠标.abs.y;
		self->m_更新绘制属性 = true;
	}
	else {
		
	}

	if (g移动控制点) {
		vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
		vec2 拾取坐标 = (mousePos - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);


		uint32 num = box->m_拾取索引.size();
		for (uint32 i = 0; i < num; ++i) {
			auto index = box->m_拾取索引[i];
			auto offset_coord = box->m_先对偏移[i];

			auto& point = box->m_动画曲线[index.组]->曲线[index.通道]->point[index.点ID];
			switch (point.Select_Type.y) {
			case DEF_CONTORL_POINT_AUTO:
				point.value = 拾取坐标 + offset_coord;
				break;
			case DEF_CONTORL_POINT_FREE:
				
				if (point.Select_Type.x & 1 << 0) {
					
					point.L_point = (point.L_point - point.value) + offset_coord + 拾取坐标;
					point.R_point = (point.R_point - point.value) + offset_coord + 拾取坐标;

					point.value = 拾取坐标 + offset_coord;
				}
				if (point.Select_Type.x & 1 << 1) {
					point.L_point = 拾取坐标;
				}
				if (point.Select_Type.x & 1 << 2) {
					point.R_point = 拾取坐标;
				}
				break;
			case DEF_CONTORL_POINT_ALGNED:
				point.L_point = (point.L_point - point.value) + offset_coord + 拾取坐标;
				point.R_point = (point.R_point - point.value) + offset_coord + 拾取坐标;
				break;
			case DEF_CONTORL_POINT_VECTOR:
				point.value = 拾取坐标 + offset_coord;
				point.L_point = (point.L_point - point.value) + offset_coord + 拾取坐标;
				point.R_point = (point.R_point - point.value) + offset_coord + 拾取坐标;
				break;
			}
			
			
		}

		for (uint32 i = 0; i < num; ++i) {
			auto index = box->m_拾取索引[i];
			auto& 曲线 = box->m_动画曲线[index.组]->曲线[index.通道];
			f_an_曲线值排序(曲线);
			f_an_自动控制点(曲线);
		}

		
		/*box->m_曲线绘制.f_map();
		for (uint32 i = 0; i < num; ++i) {
			auto index = box->m_拾取索引[i];
			auto& point = box->m_动画曲线[index.组]->曲线[index.通道]->point[index.点ID];
			box->m_曲线绘制.f_setPoint(index.GPU偏移, point);
		}
		box->m_曲线绘制.f_unmap();*/

		box->f_重建曲线绘制();
	}

	return E_事件是否传递::e_事件传递_终止;
}



static E_事件是否传递 on_曲线编辑视口准备拖动(C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data) {
	
	//g选框起点坐标 = (mousePos - box->m_扩展视口属性->m_中心) / box->m_扩展视口属性->m_比例;

	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_曲线编辑视口拖动(C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data) {
	
	auto c = f_widget_get鼠标局部位置(self->g_鼠标.gPos, self);
	int64 当前帧 = ((c.x - self->m_扩展视口属性->m_中心.x)) / self->m_扩展视口属性->m_比例.x / S_时间轴帧绘制信息::g时间区间缩放;

	f_NodeCtx_set场景当前时间(当前帧);


	return E_事件是否传递::e_事件传递_终止;
}

static bool on_曲线编辑视口结束拖放(C_Widget* self, C_Widget* 拾取的部件, S_拖放数据& data) {
	
	f_工作区_完成移动控制点(self, E_键位执行状态::e_完成);
	return true;
}

static bool on_曲线编辑视口打开关闭(C_Widget* self, bool show) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;
	C_曲线编辑视口::g当前操作曲线视口 = box;

	box->f_重建曲线绘制();

	return true;
}

C_曲线编辑视口::C_曲线编辑视口(S_UI渲染环境& ctx) : C_Widget(&ctx) {
	mf_布局 = on_曲线视口布局;
	mf_绘制 = on_曲线视口绘制;
	mf_变换 = on_曲线视口变换修改;

	mf_鼠标移动 = on_曲线视口移动;
	mf_鼠标按键按下 = on_曲线视口鼠标按下;
	mf_鼠标按键放开 = on_曲线视口鼠标放开;
	mf_键盘按键敲击 = on_曲线视口按键;
	//mf_鼠标按键点击 = on_曲线视口控制点选择;

	//mf_开始拖拽 = on_曲线编辑视口准备拖动;
	//mf_拖拽 = on_曲线编辑视口拖动;
	//mf_结束拖拽 = on_曲线编辑视口结束拖放;

	m_是否未绘制 = true;
	g当前操作曲线视口 = this;
	mui_状态条 = nullptr;

	C_曲线编辑视口::g_曲线视口页面.insert(this);
}

C_曲线编辑视口::~C_曲线编辑视口() {
	C_曲线编辑视口::g_曲线视口页面.erase(this);
}

void C_曲线编辑视口::f_旋转辅助线绘制(vec2 中心坐标, float32 角度弧度, float32 长度) {

}

void C_曲线编辑视口::f_缩放辅助线绘制(vec2 中心坐标, float32 角度弧度, float32 长度) {

}

void C_曲线编辑视口::f_重建曲线绘制() {
	
	if (m_是否未绘制 || !m_画布) {
		return;
	}
	m_拾取索引.clear();

	//auto curvs = m_动画曲线.data();
	//uint32 num = m_动画曲线.size();
	uint32 曲线组数量 = m_动画曲线.size();
	auto* curvs = m_动画曲线.data();

	uint32 所有点数量 = 0;
	for (uint32 i = 0; i < 曲线组数量; ++i) {
		auto 通道 = curvs[i];
		//迭代通道
		for (uint32 t = 0; t < 通道->count; ++t) {
			所有点数量 += 通道->曲线[t]->count;
		}
	}
	

	//m_曲线绘制.f_begin(所有点数量);

	uint32 offset = 0;
	for (uint32 i = 0; i < 曲线组数量; ++i) {
		auto 通道 = curvs[i];

		//迭代通道
		for (uint32 t = 0; t < 通道->count; ++t) {
				
			uint32 num = 通道->曲线[t]->count;
			S_CurvePoint2* point = 通道->曲线[t]->point;

			for (uint32 k = 0; k < num; ++k) {
				if (k == num - 1) {
					point[k].ID_Color.x = 0xffffffff;
				}
				else {
					point[k].ID_Color.x = offset + 1;
				}
				//m_曲线绘制.f_setPoint(offset, point[k]);
				//m_曲线绘制.f_setPointSelect(offset, point[k].Select_Type.x);

				if (point[k].Select_Type.x) {
					S_曲线扩展点拾取ID 索引 = {};

					索引.组 = i;
					索引.通道 = t;
					索引.点ID = k;
					索引.GPU偏移 = offset;
					索引.控制点 = point[k].Select_Type.x;

					m_拾取索引.push_back(索引);
				}
				
				++offset;
			}
		}
	}

	//m_曲线绘制.f_end();

}





C_曲线编辑视口* f_工作区页面_创建曲线视口(S_UI渲染环境& ctx) {
	C_曲线编辑视口* ui曲线编辑视口 = new C_曲线编辑视口(ctx);

	f_widget_开启视口属性(ui曲线编辑视口);
	ui曲线编辑视口->m_扩展视口属性->m_大小 = { 1024, 1024 };

	ui曲线编辑视口->mui_状态条 = new C_曲线编辑视口状态条(ctx);

	return ui曲线编辑视口;
}

void f_曲线视口_重构状态条(C_状态条* 状态条, C_Widget* 曲线视口) {
	C_曲线编辑视口& box = *static_cast<C_曲线编辑视口*>(曲线视口);

	std::vector<S_Props> props;

	S_Props	prop;




	props.push_back(prop);

	//状态条->f_构建属性部件(props, 状态条);
}

void f_工作区页面_设置当前编辑节点() {
	
	
}







E_事件是否传递 f_曲线页面工作区_拖拽时间帧(C_Widget* self, E_键位执行状态 状态) {
	C_曲线编辑视口& box = *(C_曲线编辑视口*)self;

	auto c = f_widget_get鼠标局部位置(self->g_鼠标.gPos, self);
	int64 当前帧 = ((c.x - self->m_扩展视口属性->m_中心.x)) / self->m_扩展视口属性->m_比例.x / S_时间轴帧绘制信息::g时间区间缩放;
	f_NodeCtx_set场景当前时间(当前帧);

	if (!g移动控制点) {
		f_时间工作区_从鼠标位置计算时间帧(self);

		//f_时间工作区_时间线绘制(box, box->m_时间线绘制);
		for (auto& e : C_曲线编辑视口::g_曲线视口页面) {
			//f_时间工作区_刷新时间线绘制(e, e->m_时间线绘制, f_NodeCtx_get帧().当前帧, self->m_父部件->m_Size.y);
		}

		f_node_帧更新(true);
		//f_node_Step节点数(1);
		//f_node_帧更新(false);
		f_工作区_联动更新(E_工作区类型::e_曲线视口, E_工作区操作类型::e_所有);
	}

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_准备框选控制点(C_Widget* self, E_键位执行状态 状态) {
	C_曲线编辑视口& box = *(C_曲线编辑视口*)self;
	
	vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	g选框起点坐标 = (mousePos);
	g选框终点坐标 = g选框起点坐标;
	return E_事件是否传递();
}

E_事件是否传递 f_工作区_拖拽曲线视口选框(C_Widget* self, E_键位执行状态 状态) {
	C_曲线编辑视口& box = *(C_曲线编辑视口*)self;

	vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	g选框终点坐标 = (mousePos);
	
	//box.m_背景绘制.f_alloc(3);
	//box.m_选框线绘制.f_alloc(1);
	//
	//mat3X2 mat;
	//mat.row0 = g选框起点坐标;
	//mat.row1 = g选框终点坐标 - mat.row0;
	//mat.row2 = { 1,0 };
	//
	//box.m_背景绘制.f_set单色填充(2, mat, S_RGBA8UI{ 60,80,160,100 }, S_Widget预设凸包图元::m_圆角矩形);
	//
	//S_LineProp lp = {0, f_PackData4X8(S_RGBA8UI{ 100,100,255,200 }), f_PackData4X8(S_RGBA8UI{ 100,100,255,200 }) };
	//box.m_选框线绘制.f_set单色线(0, mat, lp, S_Widget预设凸包图元::m_圆角矩形);

	//g移动控制点 = false;
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_框选控制点(C_Widget* self, E_键位执行状态 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	//取消移动
	//if (g移动控制点) {
	//	uint32 num = box->m_暂存位置.size();
	//
	//	if (num) {
	//		box->m_曲线绘制.f_map();
	//
	//		for (uint32 i = 0; i < num; ++i) {
	//			auto index = box->m_拾取索引[i];
	//			auto coord = box->m_暂存位置[i];
	//
	//			auto& 曲线 = box->m_动画曲线[index.组]->曲线[index.通道];
	//			auto& point = 曲线->point[index.点ID];
	//			point.value = coord.p1;
	//			point.L_point = coord.p2;
	//			point.R_point = coord.p3;
	//
	//			f_an_曲线值排序(曲线);
	//			f_an_自动控制点(曲线);
	//
	//			box->m_曲线绘制.f_setPoint(index.GPU偏移, point);
	//		}
	//		box->m_曲线绘制.f_unmap();
	//	}
	//
	//	g移动控制点 = false;
	//	return E_事件是否传递::e_事件传递_终止;
	//}
	//
	//box->m_背景绘制.f_Close(2);
	//box->m_选框线绘制.f_Close();
	//
	//
	//
	//vec2 选框起点坐标 = (g选框起点坐标 - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);
	//vec2 选框终点坐标 = (g选框终点坐标 - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);
	//
	//vec2 选框起点 = vec_Min(选框起点坐标, 选框终点坐标);
	//vec2 选框终点 = vec_Max(选框起点坐标, 选框终点坐标);
	//
	//vec2 选框大小 = 选框终点 - 选框起点;
	//
	//
	//uint32 曲线组数量 = box->m_动画曲线.size();
	//auto* curvs = box->m_动画曲线.data();
	//
	//if(选框大小.x < 2 || 选框大小.y < 2) {
	//	vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	//	vec2 拾取坐标 = (mousePos - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);
	//
	//	if (曲线组数量) {
	//		box->m_曲线绘制.f_map();
	//
	//		//清空拾取绘制焦点
	//		auto 上一次拾取控制点的索引 = box->m_拾取索引;
	//		
	//
	//		box->m_拾取索引.clear();
	//		box->m_暂存位置.clear();
	//		box->m_先对偏移.clear();
	//
	//
	//		float32 最小距离 = 3;
	//		S_曲线扩展点拾取ID 索引 = {};
	//
	//		uint32 offset = 0;
	//		vec2 coord = {};
	//		for (uint32 i = 0; i < 曲线组数量; ++i) {
	//			auto 通道 = curvs[i];
	//
	//			//迭代通道
	//			for (uint32 t = 0; t < 通道->count; ++t) {
	//				uint32 num = 通道->曲线[t]->count;
	//
	//				for (uint32 k = 0; k < num; ++k) {
	//					S_CurvePoint2& point = 通道->曲线[t]->point[k];
	//					uint32 color = point.ID_Color.y;
	//
	//					uint32 当前GPU内存偏移 = offset;
	//					++offset;
	//					std::cout<<"point.Select_Type.x = " << point.Select_Type.x << std::endl;
	//					float32 距离 = vec_len(point.value - 拾取坐标);
	//					if (距离 < 最小距离) {
	//						最小距离 = 距离;
	//
	//						索引.组 = i;
	//						索引.通道 = t;
	//						索引.点ID = k;
	//						索引.GPU偏移 = 当前GPU内存偏移;
	//						索引.控制点 = 1;
	//					}
	//
	//					距离 = vec_len(point.L_point - 拾取坐标);
	//					if (距离 < 最小距离 && point.Select_Type.x|7) {
	//						最小距离 = 距离;
	//
	//						索引.组 = i;
	//						索引.通道 = t;
	//						索引.点ID = k;
	//						索引.GPU偏移 = 当前GPU内存偏移;
	//						索引.控制点 = 1<<1;
	//					}
	//
	//					距离 = vec_len(point.R_point - 拾取坐标);
	//					if (距离 < 最小距离 && point.Select_Type.x&7) {
	//						最小距离 = 距离;
	//
	//						索引.组 = i;
	//						索引.通道 = t;
	//						索引.点ID = k;
	//						索引.GPU偏移 = 当前GPU内存偏移;
	//						索引.控制点 = 1<<2;
	//					}
	//				}
	//			}
	//		}
	//
	//
	//		//清空拾取绘制焦点
	//		for (auto& 索引 : 上一次拾取控制点的索引) {
	//			box->m_曲线绘制.f_setPointSelect(索引.GPU偏移, 0);
	//			curvs[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = 0;
	//		}
	//
	//
	//
	//		box->m_曲线绘制.f_setPointSelect(索引.GPU偏移, 索引.控制点);
	//		curvs[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = 索引.控制点;
	//
	//		box->m_曲线绘制.f_unmap();
	//
	//
	//		auto& point = curvs[索引.组]->曲线[索引.通道]->point[索引.点ID];
	//
	//		box->m_拾取索引.push_back(索引);
	//		box->m_暂存位置.push_back({point.value, point.L_point, point.R_point});
	//		box->m_先对偏移.push_back(coord - 拾取坐标);
	//	}
	//
	//}
	//else {
	//	box->m_曲线绘制.f_map();
	//	for (auto& 索引 : box->m_拾取索引) {
	//		box->m_动画曲线[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = 0;
	//		box->m_曲线绘制.f_setPointSelect(索引.GPU偏移, 0);
	//	}
	//
	//	box->m_拾取索引.clear();
	//	box->m_暂存位置.clear();
	//	box->m_先对偏移.clear();
	//
	//
	//
	//	uint32 offset = 0;
	//	for (uint32 i = 0; i < 曲线组数量; ++i) {
	//		auto 通道 = curvs[i];
	//
	//		//迭代通道
	//		for (uint32 t = 0; t < 通道->count; ++t) {
	//			uint32 num = 通道->曲线[t]->count;
	//
	//			for (uint32 k = 0; k < num; ++k) {
	//				S_CurvePoint2& point = 通道->曲线[t]->point[k];
	//				uint32 color = point.ID_Color.y;
	//
	//				uint32 当前GPU内存偏移 = offset;
	//				++offset;
	//
	//				uint32 点选择遮罩 = 0;
	//
	//				if (point.value.x < 选框起点.x || point.value.y < 选框起点.y) {
	//				}
	//				else if (point.value.x > 选框终点.x || point.value.y > 选框终点.y) {
	//				}
	//				else {
	//					点选择遮罩 |= 1<<0;
	//				}
	//
	//				if (point.L_point.x < 选框起点.x || point.L_point.y < 选框起点.y) {
	//				}
	//				else if (point.L_point.x > 选框终点.x || point.L_point.y > 选框终点.y) {
	//				}
	//				else if(point.Select_Type.x&1) {
	//					点选择遮罩 |= 1<<1;
	//				}
	//
	//				if (point.R_point.x < 选框起点.x || point.R_point.y < 选框起点.y) {
	//				}
	//				else if (point.R_point.x > 选框终点.x || point.R_point.y > 选框终点.y) {
	//				}
	//				else if(point.Select_Type.x&1) {
	//					点选择遮罩 |= 1<<2;
	//				}
	//
	//
	//				if (点选择遮罩) {
	//					point.Select_Type.x = 点选择遮罩;
	//					box->m_曲线绘制.f_setPointSelect(当前GPU内存偏移, 点选择遮罩);
	//					box->m_拾取索引.push_back({ i, t, k, 当前GPU内存偏移 });
	//				}
	//			}
	//		}
	//	}
	//
	//	box->m_曲线绘制.f_unmap();
	//}

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_点选控制点(C_Widget* self, E_键位执行状态 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	if (g移动控制点) {
		uint32 num = box->m_暂存位置.size();

		if (num) {
			//box->m_曲线绘制.f_map();
			//
			//for (uint32 i = 0; i < num; ++i) {
			//	auto index = box->m_拾取索引[i];
			//	auto coord = box->m_暂存位置[i];
			//
			//	auto& point = box->m_动画曲线[index.组]->曲线[index.通道]->point[index.点ID];
			//	point.value = coord.p1;
			//	point.L_point = coord.p2;
			//	point.R_point = coord.p3;
			//
			//	box->m_曲线绘制.f_setPoint(index.GPU偏移, point);
			//}
			//box->m_曲线绘制.f_unmap();
		}


	}
	else {

		vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
		vec2 拾取坐标 = (mousePos - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);



		uint32 曲线组数量 = box->m_动画曲线.size();
		if (曲线组数量) {
			auto* curvs = box->m_动画曲线.data();

			//box->m_曲线绘制.f_map();
			//
			////清空拾取绘制焦点
			//for (auto& 索引 : box->m_拾取索引) {
			//	box->m_曲线绘制.f_setPointSelect(索引.GPU偏移, 0);
			//	curvs[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = 0;
			//}

			box->m_拾取索引.clear();
			box->m_暂存位置.clear();
			box->m_先对偏移.clear();


			float32 最小距离 = 3;
			S_曲线扩展点拾取ID 索引 = {};

			uint32 offset = 0;
			vec2 coord = {};
			for (uint32 i = 0; i < 曲线组数量; ++i) {
				auto 通道 = curvs[i];

				//迭代通道
				for (uint32 t = 0; t < 通道->count; ++t) {
					uint32 num = 通道->曲线[t]->count;

					for (uint32 k = 0; k < num; ++k) {
						S_CurvePoint2& point = 通道->曲线[t]->point[k];
						uint32 color = point.ID_Color.y;

						uint32 当前GPU内存偏移 = offset;
						++offset;

						float32 距离 = vec_len(point.value - 拾取坐标);
						if (距离 < 最小距离) {
							最小距离 = 距离;

							索引.组 = i;
							索引.通道 = t;
							索引.点ID = k;
							索引.GPU偏移 = 当前GPU内存偏移;
							索引.控制点 = 1;
						}

						距离 = vec_len(point.L_point - 拾取坐标);
						if (距离 < 最小距离 && point.Select_Type.x&1) {
							最小距离 = 距离;

							索引.组 = i;
							索引.通道 = t;
							索引.点ID = k;
							索引.GPU偏移 = 当前GPU内存偏移;
							索引.控制点 = 1<<1;
						}

						距离 = vec_len(point.R_point - 拾取坐标);
						if (距离 < 最小距离 && point.Select_Type.x&1) {
							最小距离 = 距离;

							索引.组 = i;
							索引.通道 = t;
							索引.点ID = k;
							索引.GPU偏移 = 当前GPU内存偏移;
							索引.控制点 = 1<<2;
						}
					}
				}
			}

			//box->m_曲线绘制.f_setPointSelect(索引.GPU偏移, 索引.控制点);
			//curvs[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = 索引.控制点;
			//
			//box->m_曲线绘制.f_unmap();

			auto& point = curvs[索引.组]->曲线[索引.通道]->point[索引.点ID];
			控制点坐标 暂存位置;
			暂存位置.p1 = point.value;
			暂存位置.p2 = point.L_point;
			暂存位置.p3 = point.R_point;

			box->m_拾取索引.push_back(索引);
			box->m_暂存位置.push_back(暂存位置);
			box->m_先对偏移.push_back(coord - 拾取坐标);
		}
	}
	
	g移动控制点 = false;

	return E_事件是否传递::e_事件传递_终止;
}


E_事件是否传递 f_工作区_开启移动控制点(C_Widget* self, E_键位执行状态 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	g移动控制点 = true;

	vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	vec2 拾取坐标 = (mousePos - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);


	box->m_先对偏移.clear();
	box->m_暂存位置.clear();
	for (auto& id : box->m_拾取索引) {
		auto& coord = box->m_动画曲线[id.组]->曲线[id.通道]->point[id.点ID];
		box->m_暂存位置.push_back({coord.value, coord.L_point, coord.R_point});
		box->m_先对偏移.push_back(coord.value - 拾取坐标);
	}

	return E_事件是否传递::e_事件传递_终止;
}

/*E_事件是否传递 f_工作区_移动控制点(C_Widget* self, uint8 状态) {
	if (g移动控制点) {
	}
	return E_事件是否传递::e_事件传递_终止;
}*/

E_事件是否传递 f_工作区_完成移动控制点(C_Widget* self, E_键位执行状态 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	g移动控制点 = false;

	//box->m_拾取索引.clear();
	//box->m_暂存位置.clear();
	//box->m_先对偏移.clear();

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_取消移动控制点(C_Widget* self, E_键位执行状态 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	if (g移动控制点) {
		
	}
	
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 on_工作区_删除控制点(C_Widget* self, E_键位执行状态 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	auto it = box->m_拾取索引.begin();

	auto* curvs = box->m_动画曲线.data();

	std::set<S_曲线*> 要删除点的曲线;
	for (auto it = box->m_拾取索引.begin(); it != box->m_拾取索引.end(); ++it) {
		auto 索引 = *it;
		curvs[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = -1;

		要删除点的曲线.insert(curvs[索引.组]->曲线[索引.通道]);
	}

	for (auto& e : 要删除点的曲线) {
		uint32 num = e->count;
		for (int32 i = 0; i < num; ) {
			if (e->point[i].Select_Type.x == -1) {
				f_core_array_erase((S_Array*)e, i);
				num = e->count;
			}
			else {
				++i;
			}
		}
	}

	return E_事件是否传递::e_事件传递_终止;
}

void f_工作区_切换控制点类型(uint8 类型) {
	C_曲线编辑视口* box = C_曲线编辑视口::g当前操作曲线视口;

	for (auto& id : box->m_拾取索引) {
		auto& point = box->m_动画曲线[id.组]->曲线[id.通道]->point[id.点ID];
		
		point.Select_Type.y = 类型;

		f_an_自动控制点(box->m_动画曲线[id.组]->曲线[id.通道]);
	}
	
}

